package com.bjpowernode.app;

//静态变量在哪里？【堆里面】
//1——方法区存在一个c语言的Class对象，因此该对象里面也拥有静态变量
//2——堆区存在一个java语言的Class对象，因此该对象里面也拥有静态变量（只不过程序员是调用的堆区中的Class对象，因此对于java程序员来说静态变量在堆里面）
//堆区和方法区都是线程共享的
//堆区的数据是可以改变的，因此着重考虑线程共享同一数据的问题
//方法区的数据是不可以改变的，因此无需考虑线程共享同一数据的问题【只读】

//一个接口里面只有唯一一个抽象方法，即可以使用朗姆达表达式
//@FunctionalInterface表达该接口可以使用朗姆达表达式，表达该接口为函数接口
//朗姆达表达式：()->{}
//朗姆达表达式是弱类型语法

//线程不安全是指多线程访问共享数据，如果涉及到修改，则会发生不安全现象
//StringBuilder是线程不安全
//StringBuffer是线程安全
//List集合中线程安全的是Vector
//Set集合中线程安全的是SynchronizedSet
//Map集合中线程安全的是Hashtable
//为什么平时使用线程不安全的而不使用线程安全的【自动上锁耗费时间】

import java.util.*;
//需要解决不安全现象【同步】【没有锁就是异步【并行】】
//加锁（悲观锁）***********************************
//synchronized (锁对象)
//代码段锁住【锁对象自定义】
//方法锁住【非静态锁对象是this，静态锁对象是堆区的Class】
//上锁【第一个线程进去时刻自动上锁】
//放锁【线程执行完毕自动放锁】

public class MyApp5 {
    public static int ticket = 20;
    public Object lock = new Object();
    public boolean t = true;

    public void ticketSell(int sleep) {
        while (t) {
            synchronized (lock) {
                if (ticket > 0) {
                    try {
                        Thread.sleep(sleep);
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                    System.out.println(Thread.currentThread().getName() + ":" + ticket);
                    ticket--;
                } else {
                    t = false;
                }
            }
        }
    }

    Runnable r1 = () -> {
        ticketSell(500);

    };
    Runnable r2 = () -> {
        ticketSell(550);
    };
    Runnable r3 = () -> {
        ticketSell(600);
    };


//    IA ia = (x,y) -> {
//        System.out.println(x+y);
//    };

//    public static void main(String[] args) {
//        MyApp5 myApp5 = new MyApp5();
//        myApp5.ia.fun1(100,500);
//    }

    public static void main(String[] args) {
        MyApp5 myApp5 = new MyApp5();
        Thread thread1 = new Thread(myApp5.r1, "1号窗口");
        Thread thread2 = new Thread(myApp5.r2, "2号窗口");
        Thread thread3 = new Thread(myApp5.r3, "3号窗口");

        thread1.start();
        thread2.start();
        thread3.start();
    }

}
